using CodePlex.TfsLibrary.ObjectModel;
using CodePlex.UnitTestUtility;
using Xunit;

namespace CodePlex.CodePlexClientLibrary
{
    public class MakePatchPresenterTest
    {
        [Fact]
        public void CallsCreatePatch()
        {
            TestableMakePatchPresenter presenter = TestableMakePatchPresenter.Create();

            presenter.MakePatch(@"C:\Foo", @"C:\Foo\patch.xml");

            Assert.Equal(@"C:\Foo", presenter.PatchEngine.CreatePatch_Directory);
        }

        [Fact]
        public void MissingItemIsFilteredAndCausesViewSyncupWarning()
        {
            TestableMakePatchPresenter presenter = TestableMakePatchPresenter.Create();
            presenter.FileSystem.EnsurePath(@"C:\Foo");
            presenter.PatchEngine.CreatePatch__Result = null;
            SourceItem item = new SourceItem();
            item.LocalItemStatus = SourceItemStatus.Missing;
            SourceItemCallbackData callbackData = new SourceItemCallbackData(item, SourceItemResult.S_Ok);
            presenter.PatchEngine.CreatePatch__CallbackData.Add(callbackData);

            presenter.MakePatch(@"C:\Foo", @"C:\Foo\patch.xml");

            Assert.Null(presenter.View.ShowStatus_Item);
            Assert.True(presenter.View.ShowSyncupWarning__Called);
        }

        [Fact]
        public void NothingToPatch()
        {
            TestableMakePatchPresenter presenter = TestableMakePatchPresenter.Create();
            presenter.FileSystem.EnsurePath(@"C:\Foo");
            presenter.PatchEngine.CreatePatch__Result = null;

            presenter.MakePatch(@"C:\Foo", @"C:\Foo\patch.xml");

            Assert.True(presenter.View.ShowNothingToPatch__Called);
            Assert.False(presenter.View.ShowSyncupWarning__Called);
        }

        [Fact]
        public void NullPatchShouldNotWriteFile()
        {
            TestableMakePatchPresenter presenter = TestableMakePatchPresenter.Create();
            presenter.FileSystem.EnsurePath(@"C:\Foo");
            presenter.PatchEngine.CreatePatch__Result = null;

            presenter.MakePatch(@"C:\Foo", @"C:\Foo\patch.xml");

            Assert.False(presenter.FileSystem.FileExists(@"C:\Foo\patch.xml"));
        }

        [Fact]
        public void StatusReportedToView()
        {
            TestableMakePatchPresenter presenter = TestableMakePatchPresenter.Create();
            presenter.FileSystem.EnsurePath(@"C:\Foo");
            presenter.PatchEngine.CreatePatch__Result = "Return Value";
            SourceItemCallbackData callbackData = new SourceItemCallbackData(new SourceItem(), SourceItemResult.S_Ok);
            presenter.PatchEngine.CreatePatch__CallbackData.Add(callbackData);

            presenter.MakePatch(@"C:\Foo", @"C:\Foo\patch.xml");

            Assert.Equal(callbackData.SourceItem, presenter.View.ShowStatus_Item);
            Assert.Equal(callbackData.SourceItemResult, presenter.View.ShowStatus_Result);
            Assert.False(presenter.View.ShowNothingToPatch__Called);
            Assert.False(presenter.View.ShowSyncupWarning__Called);
        }

        [Fact]
        public void UnversionedItemIsFilteredAndCausesViewSyncupWarning()
        {
            TestableMakePatchPresenter presenter = TestableMakePatchPresenter.Create();
            presenter.FileSystem.EnsurePath(@"C:\Foo");
            presenter.PatchEngine.CreatePatch__Result = null;
            SourceItem item = new SourceItem();
            item.LocalItemStatus = SourceItemStatus.Unversioned;
            SourceItemCallbackData callbackData = new SourceItemCallbackData(item, SourceItemResult.S_Ok);
            presenter.PatchEngine.CreatePatch__CallbackData.Add(callbackData);

            presenter.MakePatch(@"C:\Foo", @"C:\Foo\patch.xml");

            Assert.Null(presenter.View.ShowStatus_Item);
            Assert.True(presenter.View.ShowSyncupWarning__Called);
        }

        [Fact]
        public void WritesFileToFileSystem()
        {
            TestableMakePatchPresenter presenter = TestableMakePatchPresenter.Create();
            presenter.FileSystem.EnsurePath(@"C:\Foo");
            presenter.PatchEngine.CreatePatch__Result = "Return Value";

            presenter.MakePatch(@"C:\Foo", @"C:\Foo\patch.xml");

            Assert.Equal(presenter.PatchEngine.CreatePatch__Result, presenter.FileSystem.ReadAllText(@"C:\Foo\patch.xml"));
        }

        class TestableMakePatchPresenter : MakePatchPresenter
        {
            public MockFileSystem FileSystem;
            public StubPatchEngine PatchEngine;
            public StubMakePatchView View;

            public TestableMakePatchPresenter(StubPatchEngine patchEngine,
                                              MockFileSystem fileSystem,
                                              StubMakePatchView view)
                : base(patchEngine, fileSystem, view)
            {
                FileSystem = fileSystem;
                View = view;
                PatchEngine = patchEngine;
            }

            public static TestableMakePatchPresenter Create()
            {
                return new TestableMakePatchPresenter(new StubPatchEngine(), new MockFileSystem(), new StubMakePatchView());
            }
        }
    }
}